package site.wuao.simplerxjava.operator;

import android.util.Log;

import java.util.ArrayList;
import java.util.List;

import rx.Observable;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.observables.GroupedObservable;
import site.wuao.simplerxjava.bean.District;

/**
 * 操作符 - 变换
 *
 * @author wuao
 * @date 2017/11/30
 * @github {https://github.com/CoderWuao}
 * @blogs {http://wuao.site/}
 * @note -
 * ---------------------------------------------------------------------------------------------------------------------
 * @modified -
 * @date -
 * @github -
 * @blogs -
 * @note -
 */
public class ChangeOperator {
    /** 标记 */
    private static final String TAG = "ChangeOperator";

    /**
     * map
     */
    public void map() {
        Observable
                .just(1, 2, 3)
                .map(new Func1<Integer, Integer>() {
                    @Override
                    public Integer call(Integer integer) {
                        return integer + 1;
                    }
                })
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.i(TAG, "call: " + integer);
                    }
                });

        // call: 2
        // call: 3
        // call: 4
    }

    /**
     * flatMap & cast
     *
     * @note flatMap的合并允许交叉
     */
    public void flatMapAndCast() {
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(i);
        }

        Observable
                .from(list)
                .flatMap(new Func1<Integer, Observable<?>>() {
                    @Override
                    public Observable<?> call(Integer integer) {
                        return Observable.just(integer + 1);
                    }
                })
                .cast(Integer.class)
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.i(TAG, "call: " + integer);
                    }
                });

        // call: 1
        // call: 2
        // call: 3
        // call: 4
        // call: 5
    }

    /**
     * ConcatMap & cast
     *
     * @note concatMap的合并解决了flatMap的交叉问题（推荐）
     */
    public void ConcatMapAndCast() {
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(i);
        }

        Observable
                .from(list)
                .concatMap(new Func1<Integer, Observable<?>>() {
                    @Override
                    public Observable<?> call(Integer integer) {
                        return Observable.just(integer + 1);
                    }
                })
                .cast(Integer.class)
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.i(TAG, "call: " + integer);
                    }
                });

        // call: 1
        // call: 2
        // call: 3
        // call: 4
        // call: 5
    }

    /**
     * flatMapIterable
     */
    public void flatMapIterable() {
        Observable
                .just(1, 2, 3)
                .flatMapIterable(new Func1<Integer, Iterable<Integer>>() {
                    @Override
                    public Iterable<Integer> call(Integer integer) {
                        List<Integer> list = new ArrayList<>();
                        list.add(integer + 1);
                        return list;
                    }
                })
                .subscribe(new Action1<Integer>() {

                    @Override
                    public void call(Integer integer) {
                        Log.i(TAG, "call: " + integer);
                    }
                });

        // call: 2
        // call: 3
        // call: 4
    }

    /**
     * buffer
     *
     * @note buffer把源Observable变换为一个新的Observable，新的Observable每次发射一组列表值
     */
    public void buffer() {
        Observable
                .just(1, 2, 3, 4, 5, 6, 7, 8, 9)
                .buffer(3)
                .subscribe(new Action1<List<Integer>>() {
                    @Override
                    public void call(List<Integer> integers) {
                        for (Integer integer : integers) {
                            Log.i(TAG, "call: " + integer);
                        }
                        Log.i(TAG, "call: " + "-----------------------");
                    }
                });

        // call: 1
        // call: 2
        // call: 3
        // call: -----------------------
        // call: 4
        // call: 5
        // call: 6
        // call: -----------------------
        // call: 7
        // call: 8
        // call: 9
        // call: -----------------------
    }

    /**
     * groupBy - 分组
     */
    public void groupBy() {
        List<District> districtList = new ArrayList<>();
        districtList.add(new District("东城区", "北京市"));
        districtList.add(new District("长宁区", "上海市"));
        districtList.add(new District("黄浦区", "上海市"));
        districtList.add(new District("江北区", "重庆市"));
        districtList.add(new District("西城区", "北京市"));
        districtList.add(new District("渝北区", "重庆市"));
        districtList.add(new District("海淀区", "北京市"));
        districtList.add(new District("徐汇区", "上海市"));
        districtList.add(new District("渝中区", "重庆市"));

        Observable<GroupedObservable<String, District>> observable =
                Observable
                        .from(districtList)
                        .groupBy(new Func1<District, String>() {
                            @Override
                            public String call(District district) {
                                return district.provinceName;
                            }
                        });

        Observable
                .concat(observable)
                .subscribe(new Action1<District>() {
                    @Override
                    public void call(District district) {
                        Log.i(TAG, "call: " + district.provinceName + district.districName);
                    }
                });

        // call: 北京市东城区
        // call: 北京市西城区
        // call: 北京市海淀区
        // call: 上海市长宁区
        // call: 上海市黄浦区
        // call: 上海市徐汇区
        // call: 重庆市江北区
        // call: 重庆市渝北区
        // call: 重庆市渝中区
    }
}

